package cz.vse.po1715.lode.net.server;

import cz.vse.po1715.lode.net.obecne.ISHrac;
import cz.vse.po1715.lode.net.obecne.Konstanty;
import cz.vse.po1715.lode.net.obecne.NIOUtils;
import cz.vse.po1715.lode.net.obecne.IHerniUdalost;
import java.nio.*;
import java.nio.channels.*;

/*******************************************************************************
 * Instance třídy {@code ZapisovačUdálostí} představují ...
 *
 * @author    Dominik KOSTKA
 * @version   0.00.000
 */
public class ZapisovačUdálostí extends ASprávceUdálostí
{
//== KONSTANTNÍ ATRIBUTY TŘÍDY =================================================
//== PROMĚNNÉ ATRIBUTY TŘÍDY ===================================================

    /** odkaz na server */
//    private static Server server;
//== STATICKÝ INICIALIZAČNÍ BLOK - STATICKÝ KONSTRUKTOR ========================
//== KONSTANTNÍ ATRIBUTY INSTANCÍ ==============================================
//== PROMĚNNÉ ATRIBUTY INSTANCÍ ================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ TŘÍDY ========================================
//== OSTATNÍ NESOUKROMÉ METODY TŘÍDY ===========================================

//##############################################################################
//== KONSTRUKTORY A TOVÁRNÍ METODY =============================================

    /***************************************************************************
     *
     */
    public ZapisovačUdálostí(Server server, int početVláken)
    {
//        ZapisovačUdálostí.server = server;
	initSprávceUdálostí(početVláken);
    }



//== ABSTRAKTNÍ METODY =========================================================
//== PŘÍSTUPOVÉ METODY VLASTNOSTÍ INSTANCÍ =====================================
//== OSTATNÍ NESOUKROMÉ METODY INSTANCÍ ========================================

    /**
     * zde překrýváme metodu run() předka SprávceUdálostí
     * metoda provádí v podstatě ty samé úkony, ale nejdříve vytvoří
     * instanci ByteBuffer pro načtení události a tu následně
     * předá přetížené verzi metody zpracujUdálosti()
     */
    @Override
    public void run() {
        ByteBuffer bb = ByteBuffer.allocateDirect(Konstanty.MAX_VELIKOST_UDÁLOSTI);
 	IHerniUdalost událost;
	běžící = true;
	while (běžící) {
	    try {
		if ((událost = vstupníFronta.vyjmi()) != null) {
		    zpracujUdálost(událost, bb);
		}
	    }
	    catch(InterruptedException e) {
	    }
	}
    }

    /**
     * nepoužíváno
     */
    @Override
    protected void zpracujUdalost(IHerniUdalost událost){
    }

    /**
     * Přetížená verze metody zpracujUdalost() která přebírá další parameter
     * v podobě Bytebufferu
     */
    protected void zpracujUdálost(IHerniUdalost událost, ByteBuffer cíl) {
	NIOUtils.pripravBuffer(událost, cíl);

	String[] příjemci = událost.getPříjemci();
	if (příjemci == null) {
	    log.info("zápis události: type=" + událost.getTyp() + ", id=" +
		     událost.getIdHrac() + ", msg=" + událost.getZprava());
	    String idHráče = událost.getIdHrac();
	    zapiš(idHráče, cíl);
	}
	else {
	    for (int i = 0; i < příjemci.length; i++) {
		if (příjemci[i] != null) {
		    log.info("zápis události(B): type=" + událost.getTyp() + ", id=" +
			     příjemci[i] + ", msg=" + událost.getZprava());
		    zapiš(příjemci[i], cíl);
		}
	    }
	}

    }

//== SOUKROMÉ A POMOCNÉ METODY TŘÍDY ===========================================
//== SOUKROMÉ A POMOCNÉ METODY INSTANCÍ ========================================

    /**
     * zapíše událost do určeného kanálu Id hráče
     */
    private void zapiš( String idHráče, ByteBuffer zdroj) {
	ISHrac player = Server.getHracPodleId(idHráče);
	SocketChannel kanál = player.getKanál();

	if (kanál == null || !kanál.isConnected()) {
	    log.info("zápis události: kanál klienta je prázdný nebo nepřipojený");
	    return;
	}

	NIOUtils.zapišDoKanálu(kanál, zdroj);
    }

//== INTERNÍ DATOVÉ TYPY =======================================================
//== TESTOVACÍ METODY A TŘÍDY ==================================================
//
//    /***************************************************************************
//     * Testovací metoda.
//     */
//    public static void test()
//    {
//        ZapisovačUdálostí inst = new ZapisovačUdálostí();
//    }
//    /** @param args Parametry příkazového řádku - nepoužívané. */
//    public static void main( String[] args )  {  test();  }
}
